<script>
import http from './common/request';
import * as msgType from './common/messageType';
import * as enums from './common/enums';
import * as wsApi from './common/wssocket';
import UNI_APP from '@/.env.js'
import push from '@/utils/push.js'

export default {
  data() {
    return {
      isInBackGroup: false,
      isExit: false, // 是否已退出
      audioTip: null,
      reconnecting: false // 正在重连标志
    }
  },
  methods: {
    init() {
      this.isExit = false;
      // 加载数据
      this.loadStore().then(() => {
        // 初始化websocket
        this.initWebSocket();
        this.initUniPush();
        this.reportCid();
      }).catch((e) => {
        console.log(e);
        this.exit();
      })
      // 好友申请，刷新页面时重新加载
    },
    initWebSocket() {
      let loginInfo = uni.getStorageSync("loginInfo")
      wsApi.init();
      wsApi.connect(UNI_APP.WS_URL, loginInfo.accessToken);
      wsApi.onConnect(() => {
        // 重连成功提示
        if (this.reconnecting) {
          this.reconnecting = false;
          uni.showToast({
            title: "已重新连接",
            icon: 'none'
          })
        }
        // 加载离线消息
        this.pullPrivateOfflineMessage(this.chatStore.privateMsgMaxId);
        this.pullGroupOfflineMessage(this.chatStore.groupMsgMaxId);
        this.pullSystemOfflineMessage(this.chatStore.systemMsgMaxSeqNo);
      });
      wsApi.onMessage((cmd, msgInfo) => {
        if (cmd == 2) {
          // 异地登录，强制下线
          uni.showModal({
            content: '您已在其他地方登陆，将被强制下线',
            showCancel: false,
          })
          this.exit();
        } else if (cmd == 3) {
          // 私聊消息
          this.handlePrivateMessage(msgInfo);
        } else if (cmd == 4) {
          // 群聊消息
          this.handleGroupMessage(msgInfo);
        } else if (cmd == 5) {
          // 系统消息
          this.handleSystemMessage(msgInfo);
        }
      });
      wsApi.onClose((res) => {
        console.log("ws断开", res);
        // 重新连接
        this.reconnectWs();

      })
    },
    loadStore() {
      return this.userStore.loadUser().then(() => {
        const promises = [];
        promises.push(this.friendStore.loadFriend());
        promises.push(this.groupStore.loadGroup());
        promises.push(this.chatStore.loadChat());
        // promises.push(this.circleStore.loadCircle());
        // promises.push(this.momentStore.loadLatestMoment());
        promises.push(this.configStore.loadConfig());
        promises.push(this.userStore.loadUserPendingCount());
        return Promise.all(promises);
      })
    },
    unloadStore() {
      this.friendStore.clear();
      this.groupStore.clear();
      this.chatStore.clear();
      this.configStore.clear();
      this.userStore.clear();
    },
    pullPrivateOfflineMessage(minId) {
      this.chatStore.setLoadingPrivateMsg(true)
      http({
        url: "/message/private/pullOfflineMessage?minId=" + minId,
        method: 'GET'
      }).catch(() => {
        this.chatStore.setLoadingPrivateMsg(false)
      })
    },
    pullGroupOfflineMessage(minId) {
      this.chatStore.setLoadingGroupMsg(true)
      http({
        url: "/message/group/pullOfflineMessage?minId=" + minId,
        method: 'GET'
      }).catch(() => {
        this.chatStore.setLoadingGroupMsg(false)
      })
    },
    pullSystemOfflineMessage(minSeqNo) {
      this.chatStore.setLoadingSystemMsg(true)
      this.$http({
        url: "/message/system/pullOfflineMessage?minSeqNo=" + minSeqNo,
        method: 'GET'
      }).catch(() => {
        this.chatStore.setLoadingSystemMsg(false)
      })
    },
    handlePrivateMessage(msg) {
      // 消息加载标志
      if (msg.type == enums.MESSAGE_TYPE.LOADING) {
        this.chatStore.setLoadingPrivateMsg(JSON.parse(msg.content))
        return;
      }
      // 消息已读处理，清空已读数量
      if (msg.type == enums.MESSAGE_TYPE.READED) {
        this.chatStore.resetUnreadCount({
          type: 'PRIVATE',
          targetId: msg.recvId
        })
        return;
      }
      // 消息回执处理,改消息状态为已读
      if (msg.type == enums.MESSAGE_TYPE.RECEIPT) {
        this.chatStore.readedMessage({
          friendId: msg.sendId
        })
        return;
      }
      // 标记这条消息是不是自己发的
      msg.selfSend = msg.sendId == this.userStore.userInfo.id;
      // 好友id
      let friendId = msg.selfSend ? msg.recvId : msg.sendId;
      this.loadFriendInfo(friendId, (friend) => {
        this.insertPrivateMessage(friend, msg);
      })
    },
    insertPrivateMessage(friend, msg) {
      // 单人视频信令
      if (msgType.isRtcPrivate(msg.type)) {
        // #ifdef MP-WEIXIN
        // 小程序不支持音视频
        return;
        // #endif
        // 被呼叫，弹出视频页面
        let delayTime = 100;
        if (msg.type == enums.MESSAGE_TYPE.RTC_SETUP_VOICE ||
            msg.type == enums.MESSAGE_TYPE.RTC_SETUP_VIDEO) {
          let mode = msg.type == enums.MESSAGE_TYPE.RTC_SETUP_VIDEO ? "video" : "voice";
          let pages = getCurrentPages();
          let curPage = pages[pages.length - 1].route;
          if (curPage != "pages/chat/chat-private-video") {
            const friendInfo = encodeURIComponent(JSON.stringify(friend));
            uni.navigateTo({
              url: `/pages/chat/chat-private-video?mode=${mode}&friend=${friendInfo}&isHost=false`
            })
            this.createNotifyMessage(friend.nickName, msg)
            delayTime = 500;
          }
        }
        setTimeout(() => {
          uni.$emit('WS_RTC_PRIVATE', msg);
        }, delayTime)
        return;
      }
      let chatInfo = {
        type: 'PRIVATE',
        targetId: friend.id,
        showName: friend.nickName,
        headImage: friend.headImage
      };
      // 打开会话
      this.chatStore.openChat(chatInfo);
      // 插入消息
      this.chatStore.insertMessage(msg, chatInfo)

      this.createNotifyMessage(friend.nickName, msg)

      // 播放提示音
      this.playAudioTip();

    },
    handleGroupMessage(msg) {
      // 消息加载标志
      if (msg.type == enums.MESSAGE_TYPE.LOADING) {
        this.chatStore.setLoadingGroupMsg(JSON.parse(msg.content))
        return;
      }
      // 消息已读处理
      if (msg.type == enums.MESSAGE_TYPE.READED) {
        // 我已读对方的消息，清空已读数量
        let chatInfo = {
          type: 'GROUP',
          targetId: msg.groupId
        }
        this.chatStore.resetUnreadCount(chatInfo)
        return;
      }
      // 消息回执处理
      if (msg.type == enums.MESSAGE_TYPE.RECEIPT) {
        let chatInfo = {
          type: 'GROUP',
          targetId: msg.groupId
        }
        // 更新消息已读人数
        let msgInfo = {
          id: msg.id,
          groupId: msg.groupId,
          readedCount: msg.readedCount,
          receiptOk: msg.receiptOk
        };
        this.chatStore.updateMessage(msgInfo, chatInfo)
        return;
      }
      // 标记这条消息是不是自己发的
      msg.selfSend = msg.sendId == this.userStore.userInfo.id;
      this.loadGroupInfo(msg.groupId, (group) => {
        // 插入群聊消息
        this.insertGroupMessage(group, msg);
      })
    },
    insertGroupMessage(group, msg) {
      // 群视频信令
      if (msgType.isRtcGroup(msg.type)) {
        // #ifdef MP-WEIXIN
        // 小程序不支持音视频
        return;
        // #endif
        // 被呼叫，弹出视频页面
        let delayTime = 100;
        if (msg.type == enums.MESSAGE_TYPE.RTC_GROUP_SETUP) {
          let pages = getCurrentPages();
          let curPage = pages[pages.length - 1].route;
          if (curPage != "pages/chat/chat-group-video") {
            const userInfos = encodeURIComponent(msg.content);
            const inviterId = msg.sendId;
            const groupId = msg.groupId;
            const url = `/pages/chat/chat-group-video?groupId=${groupId}&isHost=false
												&inviterId=${inviterId}&userInfos=${userInfos}`;
            uni.navigateTo({
              url: url
            })

            this.createNotifyMessage(group.showGroupName, msg)

            delayTime = 500;
          }
        }
        // 消息转发到chat-group-video页面进行处理
        setTimeout(() => {
          uni.$emit('WS_RTC_GROUP', msg);
        }, delayTime)
        return;
      }

      let chatInfo = {
        type: 'GROUP',
        targetId: group.id,
        showName: group.showGroupName,
        headImage: group.headImageThumb
      };
      // 打开会话
      this.chatStore.openChat(chatInfo);
      // 插入消息
      this.chatStore.insertMessage(msg, chatInfo);

      this.createNotifyMessage(group.showGroupName, msg)

      // 播放提示音
      this.playAudioTip();
    },
    handleSystemMessage(msg) {
      // 消息加载标志
      if (msg.type == this.$enums.MESSAGE_TYPE.LOADING) {
        this.chatStore.setLoadingSystemMsg(JSON.parse(msg.content));
        return;
      }
      // 消息已读处理
      if (msg.type == enums.MESSAGE_TYPE.READED) {
        // 我已读对方的消息，清空已读数量
        let chatInfo = {
          type: 'SYSTEM',
          targetId: 0
        }
        this.chatStore.resetUnreadCount(chatInfo)
        return;
      }
      if (msg.type == enums.MESSAGE_TYPE.USER_BANNED) {
        // 用户被封禁
        wsApi.close(3099);
        uni.showModal({
          content: '您的账号已被管理员封禁，原因:' + msg.content,
          showCancel: false,
        })
        this.exit();
        return;
      }
      if (msg.type == enums.MESSAGE_TYPE.USER_UNREG) {
        // 用户账号已注销
        wsApi.close(3099);
        uni.showModal({
          content: '您的账号已注销',
          showCancel: false,
        })
        this.exit();
        return;
      }

      if (msg.type == enums.MESSAGE_TYPE.SYSTEM_FRIEND_APPLY || msg.type == enums.MESSAGE_TYPE.SYSTEM_CIRCLE_APPLY) {
        // 往userStore里面插入数据
        this.userStore.loadUserPendingCount()
      }

      if (msg.type == enums.MESSAGE_TYPE.SYSTEM_FLUSH_CIRCLE) {
        console.log('flush circle list...')
        this.circleStore.loadCircle()
      }

      // 不插入消息
      if (msg.type == enums.MESSAGE_TYPE.SYSTEM_FRIEND_APPLY ||
          msg.type == enums.MESSAGE_TYPE.SYSTEM_CIRCLE_APPLY ||
          msg.type == enums.MESSAGE_TYPE.SYSTEM_FLUSH_CIRCLE) {

      } else {
        this.insertSystemMessage(msg);
      }
    },
    insertSystemMessage(msg) {
      let headImage = '/static/image/chat_system.png';
      let chatInfo = {
        type: 'SYSTEM',
        targetId: 0,
        showName: "系统通知",
        headImage: headImage
      };
      // 打开会话
      this.chatStore.openChat(chatInfo);
      // 插入消息
      this.chatStore.insertMessage(msg, chatInfo);
    },

    loadFriendInfo(id, callback) {
      let friend = this.friendStore.findFriend(id);
      if (friend) {
        callback(friend);
      } else {
        http({
          url: `/friend/find/${id}`,
          method: 'GET'
        }).then((friend) => {
          this.friendStore.addFriend(friend);
          callback(friend)
        })
      }
    },
    loadGroupInfo(id, callback) {
      let group = this.groupStore.findGroup(id);
      if (group) {
        callback(group);
      } else {
        http({
          url: `/group/find/${id}`,
          method: 'GET'
        }).then((group) => {
          this.groupStore.addGroup(group);
          callback(group)
        })
      }
    },
    exit() {
      console.log("exit");
      this.isExit = true;
      wsApi.close(3099);
      uni.removeStorageSync("loginInfo");
      uni.reLaunch({
        url: "/pages/login/login"
      })
      this.unloadStore();
    },
    playAudioTip() {
      // 音频播放无法成功
      // this.audioTip = uni.createInnerAudioContext();
      // this.audioTip.src =  "/static/audio/tip.wav";
      // this.audioTip.play();
    },
    refreshToken(loginInfo) {
      return new Promise((resolve, reject) => {
        if (!loginInfo || !loginInfo.refreshToken) {
          reject();
          return;
        }
        http({
          url: '/refreshToken',
          method: 'PUT',
          header: {
            refreshToken: loginInfo.refreshToken
          }
        }).then((newLoginInfo) => {
          uni.setStorageSync("loginInfo", newLoginInfo)
          resolve()
        }).catch((e) => {
          reject(e)
        })
      })
    },
    reconnectWs() {
      // 已退出则不再重连
      if (this.isExit) {
        return;
      }
      // 记录标志
      this.reconnecting = true;
      // 重新加载一次个人信息，目的是为了保证网络已经正常且token有效
      this.reloadUserInfo().then((userInfo) => {
        uni.showToast({
          title: '连接已断开，尝试重新连接...',
          icon: 'none'
        })
        this.userStore.setUserInfo(userInfo);
        // 重新连接
        let loginInfo = uni.getStorageSync("loginInfo")
        wsApi.reconnect(UNI_APP.WS_URL, loginInfo.accessToken);
      }).catch(() => {
        // 5s后重试
        setTimeout(() => {
          this.reconnectWs();
        }, 5000)
      })
    },
    reloadUserInfo() {
      return http({
        url: '/user/self',
        method: 'GET'
      })
    },

    createNotifyMessage(friendName, msg) {
      // #ifdef APP-PLUS
      let content = this.createNotifyContent(msg);
      // 不判断是否进入应用保持通知
      // if (!content || !this.isInBackGroup) {
      // 	return
      // };
      let options = {
        cover: true,
        title: friendName,
        icon: "./static/logo/logo.png"
      };
      uni.getStorage({
        key: 'open-voice',
        success: (res) => {
          if (res.data) {
            options.sound = "system"
          }
        },
        fail: () => {
          options.sound = "system"
        }
      });
      let body = {
        'id': 'id',
        'key': "key"
      }
      let payload = JSON.stringify(body);
      plus.push.createMessage(content, payload, options);
      this.changeBadge();
      // #endif
    },
    createNotifyContent(msg) {
      let n = msg.content;
      switch (msg.type) {
        case enums.MESSAGE_TYPE.IMAGE:
          n = "[图片]";
          break;
        case enums.MESSAGE_TYPE.VIDEO:
          n = "[视频]";
          break;
        case enums.MESSAGE_TYPE.FILE:
          n = "[文件]";
          break;
        case enums.MESSAGE_TYPE.AUDIO:
          n = "[语音]";
          break;
        case enums.MESSAGE_TYPE.RTC_SETUP_VOICE:
        case enums.MESSAGE_TYPE.RTC_SETUP_VIDEO:
          n = "邀请您进行通话";
          break;
        case enums.MESSAGE_TYPE.RTC_GROUP_SETUP:
          n = "邀请您加入通话"
      }
      return n
    },

    changeBadge(number) {
      const messages = this.getAllMessage();
      plus.runtime.setBadgeNumber(number || messages.length);
    },
    getAllMessage() {
      return plus.push.getAllMessage();
    },

    disableRightClick(event) {
      event.preventDefault();
    },
    disableInspect(event) {
      if (event.key === 'F12' || (event.ctrlKey && event.shiftKey && event.key === 'I')) {
        event.preventDefault();
      }
    },
    initUniPush() {
      // #ifdef APP-PLUS
      plus.push.setAutoNotification(true);
      plus.push.clear();
      this.changeBadge()
      const clientInfo = plus.push.getClientInfo();
      plus.push.addEventListener('click', (message) => {
        const msgInfo = message.payload;
        console.log("click:", message)
        this.onClickNotifyMessage(msgInfo);
      });
      plus.push.addEventListener('receive', (message) => {
        console.log("plus.push.addEventListener receive", message)
      });
      // #endif
    },
    onClickNotifyMessage(msgInfo) {
      if (msgInfo.type == enums.MESSAGE_TYPE.RTC_GROUP_SETUP) {
        this.$http({
          url: "/webrtc/group/info?groupId=" + msgInfo.groupId,
          method: 'GET'
        }).then((rtcInfo) => {
          if (!rtcInfo.isChating) {
            return uni.showToast({
              title: '通话已结束',
              icon: 'none'
            })
          }
          // 进入被呼叫页面
          msgInfo.content = JSON.stringify(rtcInfo.userInfos)
          setTimeout(() => this.handleGroupMessage(msgInfo), 500)
        })
      } else if (msgInfo.type == enums.MESSAGE_TYPE.RTC_SETUP_VIDEO ||
          msgInfo.type == enums.MESSAGE_TYPE.RTC_SETUP_VOICE) {
        this.$http({
          url: "/webrtc/private/info?uid=" + msgInfo.sendId,
          method: 'GET'
        }).then((rtcInfo) => {
          if (!rtcInfo.isChating) {
            return uni.showToast({
              title: '通话已结束',
              icon: 'none'
            })
          }
          // 进入被呼叫页面
          setTimeout(() => this.handlePrivateMessage(msgInfo), 500)
        })

      }
    },
    reportCid() {
      // APP需要上报cid，用于离线推送
      // #ifdef APP-PLUS
      const clientInfo = plus.push.getClientInfo();
      const cid = clientInfo.clientid;
      console.log("cid:", cid);
      http({
        url: '/user/reportCid?cid=' + cid,
        method: 'POST'
      })
      // #endif
    },
    removeCid() {
      // #ifdef APP-PLUS
      http({
        url: '/user/removeCid',
        method: 'DELETE'
      })
      // #endif
    },

    enablPermission() {
      let main = plus.android.runtimeMainActivity();
      let pkName = main.getPackageName();
      let uid = main.getApplicationInfo().plusGetAttribute("uid");
      let NotificationManagerCompat = plus.android.importClass("android.support.v4.app.NotificationManagerCompat");
      //android.support.v4升级为androidx
      if (NotificationManagerCompat == null) {
        NotificationManagerCompat = plus.android.importClass("androidx.core.app.NotificationManagerCompat");
      }
      let areNotificationsEnabled = NotificationManagerCompat.from(main).areNotificationsEnabled();

      // 未开通‘允许通知'权限，则弹窗提醒开通，并点击确认后，跳转到系统设置页面进行设置
      if (!areNotificationsEnabled) {
        uni.showModal({
          title: '通知权限开启提醒',
          content: '您还没有开启通知权限，无法接受到消息通知，请前往设置！',
          showCancel: false,
          confirmText: '去设置',
          success: function (res) {
            if (res.confirm) {
              let Intent = plus.android.importClass('android.content.Intent');
              let Build = plus.android.importClass("android.os.Build");
              //android 8.0引导
              if (Build.VERSION.SDK_INT >= 26) {
                let intent = new Intent('android.settings.APP_NOTIFICATION_SETTINGS');
                intent.putExtra('android.provider.extra.APP_PACKAGE', pkName);
              } else if (Build.VERSION.SDK_INT >= 21) { //android 5.0-7.0
                let intent = new Intent('android.settings.APP_NOTIFICATION_SETTINGS');
                intent.putExtra("app_package", pkName);
                intent.putExtra("app_uid", uid);
              } else { //(<21)其他--跳转到该应用管理的详情页
                intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                let uri = Uri.fromParts("package", mainActivity.getPackageName(), null);
                intent.setData(uri);
              }
              // 跳转到该应用的系统通知设置页
              main.startActivity(intent);
            }
          }
        });
      }
    },
  },
  onLaunch() {
    // #ifdef APP-PLUS
    this.enablPermission()
    // #endif

    this.$mountStore();
    // 登录状态校验
    let loginInfo = uni.getStorageSync("loginInfo")
    this.refreshToken(loginInfo).then(() => {
      // 初始化   有问题  打开
      this.init();
      // // 跳转到聊天页面
      // uni.switchTab({
      //   url: "/pages/chat/chat"
      // })
    }).catch(() => {
      // 跳转到登录页
      // #ifdef H5
      uni.navigateTo({
        url: "/pages/login/login"
      })
      // #endif
    })
  },

  onShow() {
    // #ifdef APP-PLUS
        plus.push.clear()
    this.changeBadge()
    // #endif
  },
  onHide() {
    // #ifdef APP-PLUS
    this.isInBackGroup = true
    // #endif
  },

  mounted() {
    // Disable right-click context menu
    document.addEventListener('contextmenu', this.disableRightClick);
    // Disable keyboard shortcuts for inspecting elements
    document.addEventListener('keydown', this.disableInspect);
  },
  beforeDestroy() {
    // Cleanup event listeners when application is destroyed
    document.removeEventListener('contextmenu', this.disableRightClick);
    document.removeEventListener('keydown', this.disableInspect);
  },
}
</script>
<style>
    /************************************************************
  ** 请将全局样式拷贝到项目的全局 CSS 文件或者当前页面的顶部 **
  ** 否则页面将无法正常显示                                  **
  ************************************************************/

  html {
    font-size: 16px;
  }

  body {
    margin: 0;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans',
      'Droid Sans', 'Helvetica Neue', 'Microsoft Yahei', sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
  }

  view,
  image,
  text {
    box-sizing: border-box;
    flex-shrink: 0;
  }

  #app {
    width: 100vw;
    height: 100vh;
  }

  .flex-row {
    display: flex;
    flex-direction: row;
  }

  .flex-col {
    display: flex;
    flex-direction: column;
  }

  .justify-start {
    justify-content: flex-start;
  }

  .justify-end {
    justify-content: flex-end;
  }

  .justify-center {
    justify-content: center;
  }

  .justify-between {
    justify-content: space-between;
  }

  .justify-around {
    justify-content: space-around;
  }

  .justify-evenly {
    justify-content: space-evenly;
  }

  .items-start {
    align-items: flex-start;
  }

  .items-end {
    align-items: flex-end;
  }

  .items-center {
    align-items: center;
  }

  .items-baseline {
    align-items: baseline;
  }

  .items-stretch {
    align-items: stretch;
  }

  .self-start {
    align-self: flex-start;
  }

  .self-end {
    align-self: flex-end;
  }

  .self-center {
    align-self: center;
  }

  .self-baseline {
    align-self: baseline;
  }

  .self-stretch {
    align-self: stretch;
  }

  .flex-1 {
    flex: 1 1 0%;
  }

  .flex-auto {
    flex: 1 1 auto;
  }

  .grow {
    flex-grow: 1;
  }

  .grow-0 {
    flex-grow: 0;
  }

  .shrink {
    flex-shrink: 1;
  }

  .shrink-0 {
    flex-shrink: 0;
  }

  .relative {
    position: relative;
  }

  .ml-2 {
    margin-left: 4rpx;
  }

  .mt-2 {
    margin-top: 4rpx;
  }

  .ml-4 {
    margin-left: 8rpx;
  }

  .mt-4 {
    margin-top: 8rpx;
  }

  .ml-6 {
    margin-left: 12rpx;
  }

  .mt-6 {
    margin-top: 12rpx;
  }

  .ml-8 {
    margin-left: 16rpx;
  }

  .mt-8 {
    margin-top: 16rpx;
  }

  .ml-10 {
    margin-left: 20rpx;
  }

  .mt-10 {
    margin-top: 20rpx;
  }

  .ml-12 {
    margin-left: 24rpx;
  }

  .mt-12 {
    margin-top: 24rpx;
  }

  .ml-14 {
    margin-left: 28rpx;
  }

  .mt-14 {
    margin-top: 28rpx;
  }

  .ml-16 {
    margin-left: 32rpx;
  }

  .mt-16 {
    margin-top: 32rpx;
  }

  .ml-18 {
    margin-left: 36rpx;
  }

  .mt-18 {
    margin-top: 36rpx;
  }

  .ml-20 {
    margin-left: 40rpx;
  }

  .mt-20 {
    margin-top: 40rpx;
  }

  .ml-22 {
    margin-left: 44rpx;
  }

  .mt-22 {
    margin-top: 44rpx;
  }

  .ml-24 {
    margin-left: 48rpx;
  }

  .mt-24 {
    margin-top: 48rpx;
  }

  .ml-26 {
    margin-left: 52rpx;
  }

  .mt-26 {
    margin-top: 52rpx;
  }

  .ml-28 {
    margin-left: 56rpx;
  }

  .mt-28 {
    margin-top: 56rpx;
  }

  .ml-30 {
    margin-left: 60rpx;
  }

  .mt-30 {
    margin-top: 60rpx;
  }

  .ml-32 {
    margin-left: 64rpx;
  }

  .mt-32 {
    margin-top: 64rpx;
  }

  .ml-34 {
    margin-left: 68rpx;
  }

  .mt-34 {
    margin-top: 68rpx;
  }

  .ml-36 {
    margin-left: 72rpx;
  }

  .mt-36 {
    margin-top: 72rpx;
  }

  .ml-38 {
    margin-left: 76rpx;
  }

  .mt-38 {
    margin-top: 76rpx;
  }

  .ml-40 {
    margin-left: 80rpx;
  }

  .mt-40 {
    margin-top: 80rpx;
  }

  .ml-42 {
    margin-left: 84rpx;
  }

  .mt-42 {
    margin-top: 84rpx;
  }

  .ml-44 {
    margin-left: 88rpx;
  }

  .mt-44 {
    margin-top: 88rpx;
  }

  .ml-46 {
    margin-left: 92rpx;
  }

  .mt-46 {
    margin-top: 92rpx;
  }

  .ml-48 {
    margin-left: 96rpx;
  }

  .mt-48 {
    margin-top: 96rpx;
  }

  .ml-50 {
    margin-left: 100rpx;
  }

  .mt-50 {
    margin-top: 100rpx;
  }

  .ml-52 {
    margin-left: 104rpx;
  }

  .mt-52 {
    margin-top: 104rpx;
  }

  .ml-54 {
    margin-left: 108rpx;
  }

  .mt-54 {
    margin-top: 108rpx;
  }

  .ml-56 {
    margin-left: 112rpx;
  }

  .mt-56 {
    margin-top: 112rpx;
  }

  .ml-58 {
    margin-left: 116rpx;
  }

  .mt-58 {
    margin-top: 116rpx;
  }

  .ml-60 {
    margin-left: 120rpx;
  }

  .mt-60 {
    margin-top: 120rpx;
  }

  .ml-62 {
    margin-left: 124rpx;
  }

  .mt-62 {
    margin-top: 124rpx;
  }

  .ml-64 {
    margin-left: 128rpx;
  }

  .mt-64 {
    margin-top: 128rpx;
  }

  .ml-66 {
    margin-left: 132rpx;
  }

  .mt-66 {
    margin-top: 132rpx;
  }

  .ml-68 {
    margin-left: 136rpx;
  }

  .mt-68 {
    margin-top: 136rpx;
  }

  .ml-70 {
    margin-left: 140rpx;
  }

  .mt-70 {
    margin-top: 140rpx;
  }

  .ml-72 {
    margin-left: 144rpx;
  }

  .mt-72 {
    margin-top: 144rpx;
  }

  .ml-74 {
    margin-left: 148rpx;
  }

  .mt-74 {
    margin-top: 148rpx;
  }

  .ml-76 {
    margin-left: 152rpx;
  }

  .mt-76 {
    margin-top: 152rpx;
  }

  .ml-78 {
    margin-left: 156rpx;
  }

  .mt-78 {
    margin-top: 156rpx;
  }

  .ml-80 {
    margin-left: 160rpx;
  }

  .mt-80 {
    margin-top: 160rpx;
  }

  .ml-82 {
    margin-left: 164rpx;
  }

  .mt-82 {
    margin-top: 164rpx;
  }

  .ml-84 {
    margin-left: 168rpx;
  }

  .mt-84 {
    margin-top: 168rpx;
  }

  .ml-86 {
    margin-left: 172rpx;
  }

  .mt-86 {
    margin-top: 172rpx;
  }

  .ml-88 {
    margin-left: 176rpx;
  }

  .mt-88 {
    margin-top: 176rpx;
  }

  .ml-90 {
    margin-left: 180rpx;
  }

  .mt-90 {
    margin-top: 180rpx;
  }

  .ml-92 {
    margin-left: 184rpx;
  }

  .mt-92 {
    margin-top: 184rpx;
  }

  .ml-94 {
    margin-left: 188rpx;
  }

  .mt-94 {
    margin-top: 188rpx;
  }

  .ml-96 {
    margin-left: 192rpx;
  }

  .mt-96 {
    margin-top: 192rpx;
  }

  .ml-98 {
    margin-left: 196rpx;
  }

  .mt-98 {
    margin-top: 196rpx;
  }

  .ml-100 {
    margin-left: 200rpx;
  }

  .mt-100 {
    margin-top: 200rpx;
  }
</style>
<style lang="scss">
@import "@/uni_modules/uview-plus/index.scss";
@import url('./static/icon/iconfont.css');

uni-image > img,
img {
  pointer-events: none;
  -webkit-pointer-events: none;
  -ms-pointer-events: none;
  -moz-pointer-events: none;
}

uni-image::before {
  content: ' ';
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background: transparent;
  opacity: 0;
}

// #ifdef H5
uni-page-head {
  display: none; // h5浏览器本身就有标题
}

// #endif

.tab-page {
  // #ifdef H5
  height: calc(100vh - 50px); // h5平台100vh是包含了底部高度，需要减去
  // #endif
  // #ifndef H5
  height: calc(100vh);
  // #endif
  // background-color: #f8f8f8;
}

.page {
  height: calc(100vh);
  // background-color: #f8f8f8;
}
</style>